Skip to content

zigamedved/chain

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

4 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

chain

Know what you're running before you run it.

chain is a supply chain risk dashboard for your projects. It surfaces lifecycle scripts that execute on npm install, CVEs from the OSV.dev database, typosquatting candidates, and missing lockfiles — before and after install, across all your projects at once.

demo

Install

brew install zigamedved/tap/chain

Or build from source:

go install github.com/zigamedved/chain/cmd/chain@latest

Commands

Command What it does
chain Dashboard across all projects — ecosystem, dep counts, risk signals
chain preview <dir> Deep view for one project: lifecycle scripts, CVEs, lockfile status
chain audit CI check — exits 1 if any HIGH signals found
chain init First-time setup wizard for scan paths

What it checks

Lifecycle scripts — packages that run arbitrary code during npm install (preinstall, install, postinstall, prepare). Detected by reading node_modules/*/package.json directly.

CVEs — batch-queried against the OSV.dev public API (no account required). Works for npm, Go modules, and PyPI. Use --offline to skip.

Lockfile signals — no package-lock.json / go.sum means installs can resolve different versions than tested.

Typosquatting — package names within edit distance 2 of the top 500 most-downloaded npm or Go packages.

Remediation

CVEs — check which version you have (npm ls <package>) and whether it's in the affected range. Then either upgrade directly:

npm update <package>

Or if it's a transitive dep you don't control, pin a resolution in package.json:

"overrides": { "lodash": "^4.17.21" }

Lifecycle scripts — read the SCRIPT column. Most prepare scripts running husky or tsc are normal dev-workflow hooks and can be ignored. Scrutinize postinstall scripts that call external services or binaries (e.g. node ./report.js, node-gyp-build). To skip all scripts on install:

npm install --ignore-scripts

No lockfile — commit a lockfile so installs are reproducible:

npm install          # generates package-lock.json
go mod tidy          # generates go.sum

Typosquatting — verify the package is what you intended (npm info <package>). If it looks wrong, remove it and install the correct one.

Usage

# scan your configured project dirs
chain

# inspect a specific project before installing
chain preview ./my-app

# same but skip the CVE network call
chain preview --offline ./my-app

# CI: fail if any HIGH-severity signal found
chain audit --path ./my-app

# fail on medium+ (stricter)
chain audit --severity medium

# include lifecycle scripts in CI failure threshold
chain audit --scripts

Reading the output

Dashboard (chain)

 PROJECT       ECOSYSTEM   DIRECT   TOTAL   SCRIPTS   SIGNALS
 my-api        node          12      847        3      ! CVE-2021-23337  ◐ no lockfile
 backend       go             8       86        —      —
 ml-pipeline   python        15        —        —      ◐ no lockfile
  • DIRECT — deps you declared in package.json / go.mod / requirements.txt
  • TOTAL — everything installed (from lockfile); means no lockfile found
  • SCRIPTS — packages with postinstall/install/prepare hooks that run on npm install; for non-node or no node_modules/
  • SIGNALS! is HIGH severity (CVE, committed secret), is MEDIUM (no lockfile, typosquat)

Audit output (chain audit)

FAIL  my-api  high  GHSA-xxxx-yyyy-zzzz in lodash
FAIL  my-api  high  postinstall script in esbuild
ok    backend

Each FAIL line is one unique finding: project · severity · advisory ID · package. The same GHSA ID will appear once per affected package, not once per lockfile entry. Exit code 1 means at least one HIGH finding; 0 means clean.

Preview (chain preview)

Shows a summary box (dep counts, CVE count, script count) followed by two tables — lifecycle scripts that will run at install time, and the full risk signal list with package name, severity, kind, and detail.

Use in CI/CD

chain audit is designed to drop into any pipeline. It exits 0 on success and 1 on findings, so it works as a standard CI gate:

GitHub Actions

- name: Dependency security check
  run: chain audit --path .

Fail on medium+ severity

- run: chain audit --severity medium --path .

Include lifecycle script signals

- run: chain audit --scripts --path .

Skip CVE network call in air-gapped environments

- run: chain audit --offline --path .

How CVE checking works

chain sends a single batch request to https://api.osv.dev/v1/querybatch with every resolved package and version from your lockfile. No API key, no account, no data stored remotely. Pass --offline to skip the network call entirely.

Ecosystem mapping: package-lock.json → npm · go.sum → Go · requirements.txt → PyPI

Scan paths

On first run, chain init asks where your projects live and writes ~/.config/chain/config.toml. Override at any time with --path:

chain --path ~/code/my-app --path ~/code/another-app

License

MIT

About

Supply chain risk visibility — know what you're running before you run it

Topics

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors

Languages